﻿//-----------------------------------------------------------------------
// <copyright file="MLPropertiesForm.cs" company="MAPILab Ltd">
//     Copyright (c) MAPILab Ltd.  All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace MAPILab.SharePoint.Explorer.ObjectBrowser
{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Windows.Forms;
    using MAPILab.SharePoint.Explorer.Information;
    using MAPILab.SharePoint.Explorer.ObjectBrowser.TreeExpand;
    using MAPILab.SharePoint.Explorer.Utilities;

    /// <summary>
    /// Properties form to customize explorer
    /// </summary>
    public partial class MLOptionsForm : Form
    {
        #region Field

        /// <summary>
        /// Is Changed properties
        /// </summary>
        bool IsChanged = false;

        /// <summary>
        /// 
        /// </summary>
        DialogResult result = DialogResult.Cancel;

        #endregion

        #region Constructor

        /// <summary>
        /// Form Constructor
        /// </summary>
        public MLOptionsForm()
        {
            InitializeComponent();
        }

        #endregion

        #region Events

        /// <summary>
        /// Form Load
        /// </summary>
        /// <param name="sender">event sender</param>
        /// <param name="e">event parameters</param>
        private void PropertiesForm_Load(object sender, EventArgs e)
        {
            OnLoad();
        }

        /// <summary>
        /// On settings change
        /// </summary>
        /// <param name="sender">event sender</param>
        /// <param name="e">event parameters</param>
        private void Change(object sender, object e)
        {
            SettingsIsChanged();
        }

        /// <summary>
        /// OK button click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OK_Click(object sender, EventArgs e)
        {
            if (IsChanged)
            {
                SaveChanges();
            }

            Close();
            DialogResult = result;
        }

        /// <summary>
        /// Cancel button click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Cancel_Click(object sender, EventArgs e)
        {
            Close();
            DialogResult = result;
        }

        /// <summary>
        /// Apply button click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Apply_Click(object sender, EventArgs e)
        {
            SaveChanges();
            SettingsIsSaved();
        }

        /// <summary>
        /// AddReference button click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AddReference_Click(object sender, EventArgs e)
        {
            AddReferanceField();
        }

        /// <summary>
        /// Remove reference button click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RemoveReference_Click(object sender, EventArgs e)
        {
            RemoveField(ReferencesGrid);
        }

        /// <summary>
        /// AddUsing button click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AddUsing_Click(object sender, EventArgs e)
        {
            AddUsingField();
        }

        /// <summary>
        /// RemoveUsing button click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RemoveUsing_Click(object sender, EventArgs e)
        {
            RemoveField(UsingsGrid);
        }

        /// <summary>
        /// help
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="hlpevent"></param>
        private void ShowHelp(object sender, HelpEventArgs hlpevent)
        {
            MLHtmlHelper.ShowTopic(this, "explorer", 121);
        }

        #endregion

        #region Methods

        /// <summary>
        /// From Loading
        /// </summary>
        private void OnLoad()
        {
            //Set default code language
            switch (Properties.Settings.Default.CodeLanguage)
            {
                case "VBNet": VBNetRadioButton.Select();
                    break;
                case "CShrap":
                default: CSharpRadioButton.Select();
                    break;
            }

            //Load default sturtup event
            sturtup_event.Checked = Properties.Settings.Default.skipDefaultLoading;           

            //Load default references
            foreach (string defRefName in Properties.Settings.Default.references)
                ReferencesGrid.Rows.Add(defRefName);

            //Load default usings
            foreach (string defUsingsName in Properties.Settings.Default.namespaces)
                UsingsGrid.Rows.Add(defUsingsName);

            //Load Rules
            foreach (string rule in Properties.Settings.Default.rulesToDisplay)
                RulesGrid.Rows.Add(rule);

            // Set events
            CSharpRadioButton.CheckedChanged += new EventHandler(Change);
            sturtup_event.CheckedChanged += new EventHandler(Change);
            ReferencesGrid.RowsAdded += new DataGridViewRowsAddedEventHandler(Change);
            ReferencesGrid.RowsRemoved += new DataGridViewRowsRemovedEventHandler(Change);
            ReferencesGrid.CellValueChanged += new DataGridViewCellEventHandler(Change);
            UsingsGrid.RowsAdded += new DataGridViewRowsAddedEventHandler(Change);
            UsingsGrid.RowsRemoved += new DataGridViewRowsRemovedEventHandler(Change);
            UsingsGrid.CellValueChanged += new DataGridViewCellEventHandler(Change);
            RulesGrid.RowsAdded += new DataGridViewRowsAddedEventHandler(Change);
            RulesGrid.RowsRemoved += new DataGridViewRowsRemovedEventHandler(Change);
            RulesGrid.CellValueChanged += new DataGridViewCellEventHandler(Change);

            SettingsIsSaved();
        }

        /// <summary>
        /// Settings are changed
        /// </summary>
        private void SettingsIsChanged()
        {
            IsChanged = true;
            Apply.Enabled = IsChanged;
        }

        /// <summary>
        /// Use it when settings are saved
        /// </summary>
        private void SettingsIsSaved()
        {
            IsChanged = false;
            Apply.Enabled = false;
        }

        /// <summary>
        /// Add New Reference
        /// </summary>
        private void AddReferanceField()
        {
            try
            {
                OpenFileDialog open = new OpenFileDialog();
                open.Multiselect = true;
                open.DefaultExt = "dll";
                open.Filter = "Unit Test Assembly Files (*.dll, *.exe)|*.dll;*.exe|All files (*.*)|*.*";
                if (open.ShowDialog() == DialogResult.OK)
                {
                    foreach (string fileName in open.FileNames)
                        ReferencesGrid.Rows.Add(fileName);
                }
            }
            catch (Exception ex)
            {
                ShowError(ex.Message);
            }
        }

        /// <summary>
        /// Add New Namespace
        /// </summary>
        private void AddUsingField()
        {
            try
            {
                MLNewNamespace newUsing = new MLNewNamespace();
                if (newUsing.ShowDialog() == DialogResult.OK)
                {
                    UsingsGrid.Rows.Add(newUsing.NewUsingLine);
                }
            }
            catch (Exception ex)
            {
                ShowError(ex.Message);
            }
        }

        /// <summary>
        /// Remove selected field from Gridview
        /// </summary>
        /// <param name="dataGridView"></param>
        private void RemoveField(DataGridView dataGridView)
        {
            foreach (DataGridViewCell cell in dataGridView.SelectedCells)
            {
                dataGridView.Rows[cell.RowIndex].Selected = true;
            }
            try
            {
                for (int i = dataGridView.Rows.Count - 1; i >= 0; i--)
                {
                    if (dataGridView.Rows[i].Selected)
                    {
                        dataGridView.Rows.RemoveAt(i);
                    }
                }
            }
            catch (Exception ex)
            {
                ShowError(ex.Message);
            }
        }

        /// <summary>
        /// Save programm settings
        /// </summary>
        private void SaveChanges()
        {
            //Save Code Language
            if (VBNetRadioButton.Checked)
            {
                Properties.Settings.Default.CodeLanguage = "VBNet";
            }
            else
            {
                Properties.Settings.Default.CodeLanguage = "CSharp";
            }

            //Save startup event checked
            Properties.Settings.Default.skipDefaultLoading = sturtup_event.Checked;

            //Save references
            Properties.Settings.Default.references.Clear();
            foreach (DataGridViewRow refRow in ReferencesGrid.Rows)
            {
                try
                {
                    string refName = refRow.Cells[0].Value as string;
                    if (!String.IsNullOrEmpty(refName) && !Properties.Settings.Default.references.Contains(refName))
                        Properties.Settings.Default.references.Add(refName);
                }
                catch (Exception ex)
                {
                    ShowError(ex.Message);
                }
            }

            //Save namespaces
            Properties.Settings.Default.namespaces.Clear();
            foreach (DataGridViewRow usingsRow in UsingsGrid.Rows)
            {
                try
                {
                    string usingsName = usingsRow.Cells[0].Value as string;
                    if (!String.IsNullOrEmpty(usingsName) && !Properties.Settings.Default.namespaces.Contains(usingsName))
                        Properties.Settings.Default.namespaces.Add(usingsName);
                }
                catch (Exception ex)
                {
                    ShowError(ex.Message);
                }
            }

            //Save rules
            Properties.Settings.Default.rulesToDisplay.Clear();
            foreach (DataGridViewRow ruleRow in RulesGrid.Rows)
            {
                try
                {
                    string rule = ruleRow.Cells[0].Value as string;

                    if (String.IsNullOrEmpty(rule))
                        continue;

                    Regex mask = new Regex(@"^ *(?<type>[a-z\.]+) *= *(?<name>[a-z\.]+) *(\: *(?<properties>[a-z_\;\%\=\(\) ]+))? *$", RegexOptions.Compiled | RegexOptions.IgnoreCase);

                    Match m = mask.Match(rule);
                    if (m.Success)
                    {
                        StringBuilder normalizedRule = new StringBuilder();

                        normalizedRule.Append(String.Format("{0} = {1}", m.Groups["type"].Value, m.Groups["name"].Value));

                        Regex maskParams = new Regex(@"(?<name>[a-z\.]+) *= *\%(?<property>[a-z_]+(\(\))?)\% *;", RegexOptions.IgnoreCase);
                        MatchCollection mc = maskParams.Matches(m.Groups["properties"].Value);
                        if (mc.Count > 0)
                        {
                            normalizedRule.Append(":");
                            foreach (Match property in mc)
                                normalizedRule.Append(String.Format(" {0}=%{1}%;", property.Groups["name"].Value, property.Groups["property"].Value));
                        }

                        Properties.Settings.Default.rulesToDisplay.Add(normalizedRule.ToString());
                    }
                }
                catch (Exception ex)
                {
                    ShowError(ex.Message);
                }
            }

            Properties.Settings.Default.Save();

            //Add rules to display items of enumerable objects
            MLUtils.AddRules();

            result = DialogResult.OK;
        }

        /// <summary>
        /// Show error messagebox
        /// </summary>
        /// <param name="text"></param>
        private void ShowError(string text)
        {
            MessageBox.Show(text, "MAPILab Explorer for SharePoint", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        #endregion
    }
}
